package top.lshaci.learning.thread;

import java.util.concurrent.TimeUnit;

/**
 * NotifyReleaseLockTest
 *
 * @author lshaci
 * @date 2020/9/7 9:15
 * @since 1.0.0
 */
public class NotifyNotReleaseLockTest {

    /**
     * jps
     * jstack $PID
     *
     * "main" #1 prio=5 os_prio=0 tid=0x0000000003382800 nid=0x4074 waiting on condition [0x000000000312f000]
     *    java.lang.Thread.State: TIMED_WAITING (sleeping)
     *         at java.lang.Thread.sleep(Native Method)
     *         at top.lshaci.learning.thread.NotifyNotReleaseLockTest.main(NotifyNotReleaseLockTest.java:60)
     *         - locked <0x000000078096eeb8> (a java.lang.Object)
     *
     * "t1" #11 prio=5 os_prio=0 tid=0x000000001bc91800 nid=0x1c74 in Object.wait() [0x000000001c5ae000]
     *    java.lang.Thread.State: BLOCKED (on object monitor)
     *         at java.lang.Object.wait(Native Method)
     *         - waiting on <0x000000078096eeb8> (a java.lang.Object)
     *         at java.lang.Object.wait(Object.java:502)
     *         at top.lshaci.learning.thread.NotifyNotReleaseLockTest.lambda$main$0(NotifyNotReleaseLockTest.java:44)
     *         - locked <0x000000078096eeb8> (a java.lang.Object)
     *         at top.lshaci.learning.thread.NotifyNotReleaseLockTest$$Lambda$1/381259350.run(Unknown Source)
     *         at java.lang.Thread.run(Thread.java:748)
     *
     * 1、定义锁lock
     * 2、t1先启动，然后调用lock.wait()释放锁，并进入等待池
     * 3、main后进入同步方法，然后调用lock.notifyAll()通知所有线程
     * 4、main调用lock.notifyAll()后没有释放锁：locked 0x000000078096eeb8
     * 5、t1接收到通知，从等待池进入锁池，并等待锁：waiting on 0x000000078096eeb8
     */
    public static void main(String[] args) throws InterruptedException {
        final Object lock = new Object();

        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                System.err.println("t1 -- IN");
                try {
                    lock.wait();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.err.println("t1 -- OUT");
            }
        }, "t1");
        t1.start();

        TimeUnit.SECONDS.sleep(1);

        synchronized (lock) {
            try {
                System.err.println("MAIN -- IN");
                lock.notifyAll();
                TimeUnit.SECONDS.sleep(10);
                System.err.println("MAIN -- OUT");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
